import sys
import sqlite3
from datetime import datetime, timezone
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *

# 数据库日期时间适配器
def adapt_datetime(dt):
    return dt.isoformat()

def convert_datetime(text):
    return datetime.fromisoformat(text.decode())

sqlite3.register_adapter(datetime, adapt_datetime)
sqlite3.register_converter("datetime", convert_datetime)

class MemoryApp(QMainWindow):
    def __init__(self):
        super().__init__()
        self.db = sqlite3.connect('cards.db', detect_types=sqlite3.PARSE_DECLTYPES)
        self.init_db()
        self.current_card = None
        self.answer_visible = False
        self.current_tag_filter = None
        self.filtered_cards = []
        self.current_card_index = -1
        self.init_ui()
        self.load_next_card()

    def init_db(self):
        c = self.db.cursor()
        c.execute('''CREATE TABLE IF NOT EXISTS cards
            (id INTEGER PRIMARY KEY,
             question TEXT,
             answer TEXT,
             proficiency INTEGER DEFAULT 0,
             modified DATETIME)''')
        c.execute('''CREATE TABLE IF NOT EXISTS tags
            (id INTEGER PRIMARY KEY, name TEXT UNIQUE)''')
        c.execute('''CREATE TABLE IF NOT EXISTS card_tags
            (card_id INTEGER, tag_id INTEGER,
             FOREIGN KEY(card_id) REFERENCES cards(id),
             FOREIGN KEY(tag_id) REFERENCES tags(id))''')
        self.db.commit()

    def init_ui(self):
        self.setWindowTitle('智能记忆训练系统')
        self.setGeometry(300, 300, 800, 600)
        
        central = QWidget()
        self.setCentralWidget(central)
        layout = QVBoxLayout(central)
        
        # 标签显示
        self.tags_label = QLabel()
        self.tags_label.setStyleSheet("color: #666; font-size: 12px;")
        layout.addWidget(self.tags_label)
        
        # 卡片显示区域
        self.card_display = QTextEdit()
        self.card_display.setReadOnly(True)
        self.card_display.setStyleSheet("""
            QTextEdit {
                font-size: 20px;
                padding: 30px;
                border: 2px solid #eee;
                border-radius: 10px;
                margin: 15px;
            }
        """)
        layout.addWidget(self.card_display)
        
        # 控制按钮
        btn_layout = QHBoxLayout()
        self.start_btn = self.create_button("开始学习 (S)", self.start_study_session)
        self.add_btn = self.create_button("添加卡片 (A)", self.add_card)
        self.edit_btn = self.create_button("编辑卡片 (D)", self.edit_card)
        self.prev_btn = self.create_button("上一个 (Q)", self.prev_card)
        self.next_btn = self.create_button("下一个 (E)", self.next_card)
        self.help_btn = self.create_button("帮助 (H)", self.show_help)
        
        for btn in [self.start_btn, self.add_btn, self.edit_btn,
                    self.prev_btn, self.next_btn, self.help_btn]:
            btn_layout.addWidget(btn)
        layout.addLayout(btn_layout)
        
        # 状态栏
        self.status = self.statusBar()
        self.update_status()
        
        # 快捷键设置
        shortcuts = {
            Qt.Key_Space: self.toggle_answer,
            Qt.Key_Q: self.prev_card,
            Qt.Key_E: self.next_card,
            Qt.Key_A: self.add_card,
            Qt.Key_D: self.edit_card,
            Qt.Key_S: self.start_study_session,
            Qt.Key_H: self.show_help,
            Qt.Key_1: lambda: self.rate_card(1),
            Qt.Key_2: lambda: self.rate_card(2),
            Qt.Key_3: lambda: self.rate_card(3)
        }
        for key, func in shortcuts.items():
            QShortcut(key, self).activated.connect(func)

    def create_button(self, text, callback):
        btn = QPushButton(text)
        btn.setStyleSheet("""
            QPushButton {
                padding: 8px;
                background: #4CAF50;
                color: white;
                border-radius: 4px;
            }
            QPushButton:hover {
                background: #45a049;
            }
        """)
        btn.clicked.connect(callback)
        return btn

    def add_card(self):
        dialog = CardEditDialog("", "", [], self.get_all_tags(), self)
        if dialog.exec_() == QDialog.Accepted:
            question, answer, tags = dialog.get_data()
            c = self.db.cursor()
            current_time = datetime.now(timezone.utc).replace(tzinfo=None)
            
            c.execute('''INSERT INTO cards 
                      (question, answer, modified)
                      VALUES (?, ?, ?)''', 
                     (question, answer, current_time))
            card_id = c.lastrowid
            self.update_card_tags(card_id, tags)
            self.db.commit()
            self.load_next_card(force_refresh=True)

    def edit_card(self):
        if not self.current_card:
            return
            
        dialog = CardEditDialog(
            self.current_card[1], 
            self.current_card[2],
            self.get_card_tags(self.current_card[0]),
            self.get_all_tags(),
            self
        )
        if dialog.exec_() == QDialog.Accepted:
            question, answer, tags = dialog.get_data()
            c = self.db.cursor()
            c.execute('''UPDATE cards SET question=?, answer=?, modified=?
                      WHERE id=?''', 
                     (question, answer, datetime.now(timezone.utc), self.current_card[0]))
            self.update_card_tags(self.current_card[0], tags)
            self.db.commit()
            self.load_next_card(force_refresh=True)

    def update_card_tags(self, card_id, new_tags):
        c = self.db.cursor()
        c.execute("DELETE FROM card_tags WHERE card_id=?", (card_id,))
        for tag_id in new_tags:
            c.execute("INSERT INTO card_tags VALUES (?, ?)", (card_id, tag_id))
        self.db.commit()

    def get_all_tags(self):
        c = self.db.cursor()
        c.execute("SELECT id, name FROM tags ORDER BY name")
        return c.fetchall()

    def get_card_tags(self, card_id):
        c = self.db.cursor()
        c.execute('''SELECT t.id, t.name FROM tags t
                   JOIN card_tags ct ON t.id = ct.tag_id
                   WHERE ct.card_id = ?''', (card_id,))
        return c.fetchall()

    def start_study_session(self):
        tags = self.get_all_tags()
        if not tags:
            QMessageBox.information(self, "提示", "请先创建标签")
            return

        tag_names = [t[1] for t in tags]
        selected_tag, ok = QInputDialog.getItem(
            self, "选择标签", "请选择要学习的标签:", tag_names, editable=False
        )
        if ok and selected_tag:
            self.current_tag_filter = selected_tag
            self.load_filtered_cards()
            if self.filtered_cards:
                self.current_card_index = 0
                self.show_current_card()
            else:
                QMessageBox.information(self, "提示", "该标签下无可用卡片")

    def load_filtered_cards(self):
        c = self.db.cursor()
        query = '''SELECT c.* FROM cards c
                JOIN card_tags ct ON c.id = ct.card_id
                JOIN tags t ON ct.tag_id = t.id
                WHERE t.name = ?
                ORDER BY 
                    CASE 
                        WHEN proficiency < 30 THEN 0
                        WHEN proficiency < 70 THEN 1
                        ELSE 2
                    END,
                    RANDOM()'''
        c.execute(query, (self.current_tag_filter,))
        self.filtered_cards = c.fetchall()

    def show_current_card(self):
        if 0 <= self.current_card_index < len(self.filtered_cards):
            self.current_card = self.filtered_cards[self.current_card_index]
            self.answer_visible = False
            self.update_display()
            self.update_status()

    def prev_card(self):
        if self.current_tag_filter:
            self.current_card_index = max(0, self.current_card_index - 1)
            self.show_current_card()
        else:
            if self.current_card:
                c = self.db.cursor()
                c.execute('''SELECT * FROM cards 
                          WHERE id < ? 
                          ORDER BY id DESC 
                          LIMIT 1''', (self.current_card[0],))
                prev_card = c.fetchone()
                if prev_card:
                    self.current_card = prev_card
                    self.answer_visible = False
                    self.update_display()

    def next_card(self):
        if self.current_tag_filter:
            if self.current_card_index < len(self.filtered_cards) - 1:
                self.current_card_index += 1
            else:
                self.current_card_index = 0  # 循环到开头
            self.show_current_card()
        else:
            self.load_next_card()

    def load_next_card(self, force_refresh=False):
        try:
            c = self.db.cursor()
            if force_refresh or not self.current_tag_filter:
                c.execute('''SELECT * FROM cards 
                          ORDER BY RANDOM() 
                          LIMIT 1''')
                self.current_card = c.fetchone()
            self.answer_visible = False
            self.update_display()
        except Exception as e:
            print("加载卡片错误:", e)

    def rate_card(self, rating):
        if not self.current_card:
            return
        
        card_id = self.current_card[0]
        new_proficiency = self.current_card[3]
        
        # 调整熟练度
        if rating == 1:   # 不熟悉
            new_proficiency = max(0, new_proficiency - 20)
        elif rating == 2: # 一般
            new_proficiency = min(100, new_proficiency + 10)
        elif rating == 3: # 熟练
            new_proficiency = min(100, new_proficiency + 30)
        
        # 更新数据库
        c = self.db.cursor()
        c.execute('''UPDATE cards SET proficiency=?, modified=?
                  WHERE id=?''',
                 (new_proficiency, datetime.now(timezone.utc), card_id))
        self.db.commit()
        
        # 自动切换卡片
        if self.current_tag_filter:
            self.next_card()
        else:
            self.load_next_card(force_refresh=True)

    def update_display(self):
        if self.current_card:
            proficiency_bar = self.create_proficiency_bar(self.current_card[3])
            tags = self.get_card_tags(self.current_card[0])
            text = f"""
                <div style='margin-bottom: 15px;'>{proficiency_bar}</div>
                <div style='font-size: 22px;'>{self.current_card[1]}</div>
                {self.show_answer_section()}
                <div style='color: #666; margin-top: 20px;'>
                    标签: {', '.join(t[1] for t in tags)}
                </div>
            """
            self.card_display.setHtml(text)
        else:
            self.card_display.setText("无可用卡片")
        self.update_status()

    def create_proficiency_bar(self, percentage):
        color = "#ff4444" if percentage < 30 else "#4CAF50" if percentage < 70 else "#2196F3"
        return f"""
            <div style='background: #f0f0f0; height: 20px; border-radius: 10px;'>
                <div style='width: {percentage}%; background: {color}; 
                     height: 100%; border-radius: 10px; 
                     transition: width 0.3s ease;'></div>
            </div>
        """

    def show_answer_section(self):
        if self.answer_visible:
            return f"""
                <hr style='margin: 20px 0;'>
                <div style='color: #666; font-size: 18px;'>
                    {self.current_card[2]}
                </div>
            """
        return ""

    def update_status(self):
        status = []
        if self.current_tag_filter:
            status.append(f"学习模式: {self.current_tag_filter}")
            status.append(f"进度: {self.current_card_index+1}/{len(self.filtered_cards)}")
        
        c = self.db.cursor()
        c.execute("SELECT COUNT(*) FROM cards")
        total = c.fetchone()[0]
        
        status.append(f"总卡片: {total}")
        if self.current_card:
            status.append(f"熟练度: {self.current_card[3]}%")
            status.append("←Q 上一个 | E→ 下一个")
        
        self.status.showMessage(" | ".join(status))

    def toggle_answer(self):
        if self.current_card:
            self.answer_visible = not self.answer_visible
            self.update_display()

    def show_help(self):
        help_text = """<b>智能记忆系统 使用指南</b>

        <u>核心功能</u>
        • 添加卡片: <i>A键</i> - 创建新记忆点
        • 学习模式: <i>S键</i> - 按掌握程度智能排序
        • 三维评分: 
          1键: 不熟悉（红区）
          2键: 一般（绿区）  
          3键: 熟练（蓝区）

        <u>导航系统</u>
        • 上一个卡片: Q键
        • 下一个卡片: E键
        • 显示答案: 空格键

        <u>可视化系统</u>
        • 彩色进度条实时显示掌握程度
        • 标签分类管理系统
        • 智能学习进度跟踪"""
        
        msg = QMessageBox(self)
        msg.setIcon(QMessageBox.Information)
        msg.setWindowTitle("系统帮助")
        msg.setTextFormat(Qt.RichText)
        msg.setText(help_text)
        msg.setStandardButtons(QMessageBox.Ok)
        msg.exec_()

    def closeEvent(self, event):
        self.db.close()

class CardEditDialog(QDialog):
    def __init__(self, question, answer, current_tags, all_tags, parent=None):
        super().__init__(parent)
        self.setWindowTitle("卡片编辑器")
        self.setFixedSize(600, 500)
        
        layout = QVBoxLayout()
        
        # 问题输入
        self.question_edit = QTextEdit()
        self.question_edit.setPlainText(question)
        self.question_edit.setPlaceholderText("输入问题...")
        layout.addWidget(QLabel("问题:"))
        layout.addWidget(self.question_edit)
        
        # 答案输入
        self.answer_edit = QTextEdit()
        self.answer_edit.setPlainText(answer)
        self.answer_edit.setPlaceholderText("输入答案...")
        layout.addWidget(QLabel("答案:"))
        layout.addWidget(self.answer_edit)
        
        # 标签选择器
        self.tag_widget = TagSelector(current_tags, all_tags)
        layout.addWidget(QLabel("关联标签:"))
        layout.addWidget(self.tag_widget)
        
        # 按钮组
        btn_box = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
        btn_box.accepted.connect(self.accept)
        btn_box.rejected.connect(self.reject)
        layout.addWidget(btn_box)
        
        self.setLayout(layout)

    def get_data(self):
        return (
            self.question_edit.toPlainText().strip(),
            self.answer_edit.toPlainText().strip(),
            self.tag_widget.selected_tags()
        )

class TagSelector(QWidget):
    def __init__(self, current_tags, all_tags):
        super().__init__()
        self.all_tags = {t[1]: t[0] for t in all_tags}
        self.current_tag_ids = {t[0] for t in current_tags}
        
        layout = QHBoxLayout()
        
        # 标签列表
        self.tag_list = QListWidget()
        self.tag_list.setSelectionMode(QListWidget.MultiSelection)
        self.load_tags(all_tags)
        layout.addWidget(self.tag_list)
        
        # 新建标签区
        self.new_tag_edit = QLineEdit()
        self.new_tag_edit.setPlaceholderText("输入新标签...")
        self.new_tag_btn = QPushButton("创建")
        self.new_tag_btn.clicked.connect(self.create_tag)
        
        v_layout = QVBoxLayout()
        v_layout.addWidget(self.new_tag_edit)
        v_layout.addWidget(self.new_tag_btn)
        layout.addLayout(v_layout)
        
        self.setLayout(layout)

    def load_tags(self, tags):
        self.tag_list.clear()
        for tag_id, name in tags:
            item = QListWidgetItem(name)
            item.setData(Qt.UserRole, tag_id)
            item.setSelected(tag_id in self.current_tag_ids)
            self.tag_list.addItem(item)

    def create_tag(self):
        name = self.new_tag_edit.text().strip()
        if name and name not in self.all_tags:
            c = self.parent().parent().db.cursor()
            c.execute("INSERT INTO tags (name) VALUES (?)", (name,))
            c.connection.commit()
            self.all_tags[name] = c.lastrowid
            self.load_tags([(self.all_tags[name], name)])

    def selected_tags(self):
        return [item.data(Qt.UserRole) for item in self.tag_list.selectedItems()]

if __name__ == '__main__':
    app = QApplication(sys.argv)
    app.setStyle('Fusion')
    
    # 设置全局字体
    font = QFont()
    font.setFamily("微软雅黑")
    font.setPointSize(10)
    app.setFont(font)
    
    window = MemoryApp()
    window.show()
    sys.exit(app.exec_())